/* DISCLAIMER
Original file written by Johnny on Flame.
This piece is protected by the GPLv3 License. Commercial uses of this should only happen with my consent.
JohnnyonFlame (a_t) Hotmail (d_o_t) com
----------------------------------------------------------
This class deals with XML Parsing.
It transforms a raw XML File into the lists you see.
Behind the flexibily of the menus, there's alot of hardcoded,
Messy as hell code.

Good luck in understanding what I wrote here.
You're gonna need it.
----------------------------------------------------------*/
#include "menu.h"
#include "items.h"
#include "xmlLoader.h"
#include "settings.h"
#include "callbacks.h"
#include "iniparser.h"

#include <stdio.h>
#include <libxml/tree.h>

void load_XML(char *file){

	xmlDocPtr doc;
	xmlNodePtr m_node, node;
	doc = xmlParseFile(file);

	patch_XML("cfg/hexen.desktop", doc);
		
	//

	m_node = doc->children;	
	
	if (m_node->children){
		node=m_node->children;
		for(;;){
			if (strcmp(node->name,"text")==0) { if (node->next) { node=node->next; continue; } else break; }
			if (strcmp(node->name,"mainMenu")==0) node_MakeMenu(NULL,NULL,node); //Starts the recursive menu building functions
			if (node->next) node=node->next; else break;
		}
	}

	xmlFreeDoc(doc);
}

/*[Desktop Entry]
Type=Application
Name=HeXen
GenericName=hhexen
Comment=Fight against the Serpent Riders in\nHexen: Beyond Heretic.
Path=/boot/local/bin/hhexen/
Exec=./hhexen.dge
Icon=hexen
Categories=Emulator;Gameboy;
X-OD-OpenWithFile=false
X-OD-IsConsoleApp=false*/

void patch_XML(char *patch, xmlDocPtr doc){
	dictionary *ini;
	ini = iniparser_load(patch);

	char *cat;

	if (ini==NULL) {
	fprintf(stderr, "cannot parse file: %s\n", patch);
	return;
	}	
		
	//node = findNodeById(doc->children->children, "Games");
	xmlNodePtr n, node;

	cat = iniparser_getstring(ini, "Desktop Entry:Categories", NULL);
	char *str = strtok (cat,";");
	while (str!=NULL) {
		n = findNodeById(doc->children->children, str);
		if (n!=NULL)
			node = n;
		str= strtok (NULL,";");
	}
	if (node) {
		n = xmlNewNode(NULL, "binary");
		xmlSetProp(n, "label", iniparser_getstring(ini, "Desktop Entry:Name", NULL));
		xmlSetProp(n, "path", iniparser_getstring(ini, "Desktop Entry:Path", NULL));
		xmlSetProp(n, "file", iniparser_getstring(ini, "Desktop Entry:Exec", NULL));
		char *overlay;
		overlay = iniparser_getstring(ini, "Desktop Entry:Path", NULL);
		overlay = Concatenate(overlay, iniparser_getstring(ini, "Desktop Entry:Icon", NULL));
		overlay = Concatenate(overlay, "_overlay.png");
		xmlSetProp(n, "overlay",  overlay);
		/*xmlSetProp(n, name, value);
		xmlSetProp(n, name, value);
		xmlSetProp(n, name, value);
		xmlSetProp(n, name, value);*/
		xmlAddChild(node, n);
	}

    	iniparser_freedict(ini);
}

xmlNodePtr findNodeById(xmlNodePtr node_, char* id){
	xmlNodePtr node, rnode, tnode;
	rnode = NULL;	
	node = node_;

	for (;;) {
		if (strcmp(node->name,"text")==0) { if (node->next) { node=node->next; continue; } else break; }
		if (xmlGetProp(node, "cat")) {
			if (strcmp(xmlGetProp(node, "cat"),id) == 0) { 
				rnode=node;
				break; 
			}
		}

		if (node->children)
			tnode = findNodeById(node->children, id);
		if (tnode) {
			rnode = tnode;
			break;
		} 
		if (node->next) node=node->next; else break;
	}
	return rnode;
}

void load_SETTINGS(char *file){

	xmlDocPtr doc;

	xmlNodePtr m_node, node;

	doc = xmlParseFile(file);
	m_node = doc->children;
	//BUILD MENUS, LOAD SETTINGS
	if (m_node->children){
		node=m_node->children;
		for(;;){
			if (strcmp(node->name,"text")==0) { if (node->next) { node=node->next; continue; } else break; }
			if (strcmp(node->name,"setting")==0) applySetting(node);
			if (node->next) node=node->next; else break;
		}
	}

	xmlFreeDoc(doc);
}

//Recursive function that takes care of filling the whole ram with menus.
void node_MakeMenu(List_Items* previous, List_Item *item, xmlNodePtr list){

	int count=0;
	if (list->children){ //Counts the number of items it needs to allocate in the menu
		xmlNodePtr node = list->children;
		for(;;) {
			if (strcmp(node->name,"text")==0) { if (node->next) { node=node->next; continue; } else break; }
			count++;
			if (node->next) node=node->next; else break;
		}
	}

	//Allocates COUNT + 1 in case there is a menu under this in the tree (back item), or else, just allocs. COUNT.
	List_Items* list_items = List_Alloc(count + ((previous==NULL)?0:1));	
	list_items->previous = previous;

	//Counts and Points the allocated menu into the GARBAGE COLLECTOR, noone likes memory leaks.
	garbage_ammount++;
	garbage_collector[garbage_ammount] = (void*)list_items;

	int i=-1;
	
	if (list->children){ //Iterates throughout the NODE we're navigating creating items and magic.
		xmlNodePtr node = list->children;
		for(;;) {
			if (strcmp(node->name,"text")==0) { if (node->next) { node=node->next; continue; } else break; } //Skips BOGUS 
			i++;

			/*char strbb[] = "ohdamn";
			list_items->items[i].type = xmlGetProp(node, "name");*/

			list_items->items[i].type = (char *)malloc(strlen(node->name)+1);
			strcpy(list_items->items[i].type, node->name);
			//Checks if the LABEL prop is present on the XML file, if so, names it, else, it just names it ?.
			if (xmlGetProp(node, "label"))
				list_items->items[i].label = xmlGetProp(node, "label"); 
			else 
				list_items->items[i].label = "?";

			//Checks for the OVERLAY Prop is present, if not, it is nill'd to avoid randomness/segfaults
			if (xmlGetProp(node, "overlay")) 
				list_items->items[i].overlay_file = xmlGetProp(node, "overlay"); 
			else 
				list_items->items[i].overlay_file = NULL;

			//Runs another iteraction of this function, creating another (sub)menu.
			if (strcmp(node->name,"list")==0) {
				node_MakeMenu( list_items, &list_items->items[i], node);
			} else

			if (strcmp(node->name,"list_apps")==0) {
				node_MakeMenu( list_items, &list_items->items[i], node);
			} else

			//Creates a BINARY launcher item, takes care of launching Apps, Games and Others.
			if (strcmp(node->name,"binary")==0) {
				if (xmlGetProp(node, "path")) {
					if (xmlGetProp(node, "overlay_path")) { //Checks if it uses PATH Overlays, for binaries stored in a folder with all the files.
						list_items->items[i].overlay_file = Concatenate(xmlGetProp(node, "path"), xmlGetProp(node, "overlay_path"));
					}
					if (xmlGetProp(node, "file")) { //Sets the path of the binary file.
						list_items->items[i].arga = xmlGetProp(node, "file");
						list_items->items[i].argb = xmlGetProp(node, "path");
						list_items->items[i].funcCallback = Menu_BIN;
					}
				}
			} else

			if (strcmp(node->name,"cmd")==0) {
				if (xmlGetProp(node, "value")) {
					list_items->items[i].arga = xmlGetProp(node, "value");
					list_items->items[i].funcCallback = Menu_CMD;
				}
			}

			if (node->next) node=node->next; else break;
		}
	}
	if (previous==NULL) {
		display_menu= list_items;
	}
	else
	{
		i++;
		list_items->items[i].label = "Back";
		list_items->items[i].type = "Back";
		list_items->items[i].arga = previous;
		list_items->items[i].funcCallback = Menu_Step;

		item->funcCallback = Menu_Step;
		item->arga = list_items;
	}
}


